//-----------------------------------------------------------------------------
// File: AboutDevice.cs
//
// Copyright (c) Dmitry Shuklin. All rights reserved.
//-----------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;


namespace ObjectiveDraw.Platform.Information
{
	/// <summary>
	/// Summary description for CreditsDevice.
	/// </summary>
	internal class AboutDevice : Cerebrum.Direct3D.Forms.DeviceControl
	{
		System.Drawing.Bitmap m_TextureBitmap;

		object m__ImageTexture = new object();
		object m__VertexBuffer = new object();

		private Cerebrum.Direct3D.Forms.ControlRepeater m_ControlRepeater;
		private Cerebrum.Direct3D.Drawing.Font m_Direct3DFont;
		private System.Drawing.Font m_WindowsFont;
		private string[] m_TextLines;

		internal AboutDevice()
		{
			//
			// TODO: Add constructor logic here
			//
			string message = FromString("DQpTSERzb2Z0d2FyZSBPYmplY3RpdmUgRHJhdw0KDQpBdWd1c3QsIDIwMDYgLSBNYXksIDIwMDgNCg0KDQoNCg0KY2hpZWYgc29mdHdhcmUgYXJjaGl0ZWN0Og0KDQpEbWl0cnkgU2h1a2xpbg0KDQoNCg0KDQpwcm9ncmFtbWluZzoNCg0KRG1pdHJ5IFNodWtsaW4sDQpTZXJnZXkgQm95a28sDQpBbGV4YW5kZXIgQ296dWJlcmRhLA0KVmxhZGltaXIgTGVzaGNoaW5za3kNCg0KDQoNCg==");

			m_TextLines = message.Replace("\r", "").Split('\n');
			m_WindowsFont = new System.Drawing.Font("Verdana", 12);
			System.Drawing.Brush brush = new System.Drawing.SolidBrush(System.Drawing.Color.Yellow);

			System.Drawing.StringFormat format = new System.Drawing.StringFormat();
			format.Alignment = System.Drawing.StringAlignment.Center;

			InitializeComponent();

			//m_TextureBitmap = DrawTextToBitmap(message, m_WindowsFont, brush, format);
			m_TextureBitmap = null;

		}

		private void InitializeComponent()
		{
			// 
			// CreditsDevice
			// 
			this.ForeColor = System.Drawing.Color.Black;

			this.m_Direct3DFont = new Cerebrum.Direct3D.Drawing.Font(this.m_WindowsFont);

			// repeater1
			this.m_ControlRepeater = new Cerebrum.Direct3D.Forms.ControlRepeater();
			this.m_ControlRepeater.Dock = System.Windows.Forms.DockStyle.Fill;
			this.m_ControlRepeater.Location = new System.Drawing.PointF(5, 5);
			this.m_ControlRepeater.Size = new System.Drawing.SizeF(200, 200);
			this.m_ControlRepeater.CreateRepeatedControl += new Cerebrum.Direct3D.Forms.CreateRepeatedEventHandler(ControlRepeater_CreateRepeatedControl);
			this.Controls.Add(this.m_ControlRepeater);
		}

		public static string FromString(string s)
		{
			string r;
			byte [] buff = Convert.FromBase64String(s);
			System.IO.MemoryStream ms = new System.IO.MemoryStream(buff);
			System.IO.StreamReader sr = new System.IO.StreamReader(ms);
			r = sr.ReadToEnd();
			sr.Close();
			ms.Close();
			return r;
		}

		protected override void OnInitializeDeviceObjects(Cerebrum.Direct3D.Forms.DeviceEventArgs e)
		{
			base.OnInitializeDeviceObjects (e);
			this.m_Direct3DFont.InitializeDeviceObjects(e.Device);
			m_ControlRepeater.ControlsCount = m_TextLines.Length;
		}

		private System.DateTime m_DeviceTime;

		protected override void OnUpdateScene(Cerebrum.Direct3D.Forms.DeviceEventArgs e)
		{

			System.DateTime time = System.DateTime.Now;

			m_DeviceTime = new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second);

			base.OnUpdateScene (e);

			// Setup the lights and materials
			SetupLights();
			// Setup the world, view, and projection matrices
			SetupMatrices();
		}
		
		/// <summary>
		/// Called once per frame, the call is the entry point for 3d rendering. This 
		/// function sets up render states, clears the viewport, and renders the scene.
		/// </summary>
		protected override void OnRenderScene(Cerebrum.Direct3D.Forms.RenderEventArgs e)
		{
			//Clear the backbuffer to a black color 
			m_Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, this.ForeColor, 1.0f, 0);
			
			//Begin the scene
			m_Device.BeginScene();

			base.OnRenderScene (e);

			if(m_TextureBitmap!=null)
			{
				RectangleF rectangle = new RectangleF(0,0,m_TextureBitmap.Width,m_TextureBitmap.Height);


				Texture _ImageTexture = Cerebrum.Direct3D.Drawing.Graphics.DeviceObjects[e.Device, m__ImageTexture] as Texture;

				if(_ImageTexture == null)
				{
					_ImageTexture = Texture.FromBitmap(e.Device, m_TextureBitmap, 0, Pool.Managed);
					Cerebrum.Direct3D.Drawing.Graphics.DeviceObjects[e.Device, m__ImageTexture] = _ImageTexture;
				}
				
				VertexBuffer _VertexBuffer = Cerebrum.Direct3D.Drawing.Graphics.DeviceObjects[m_Device, m__VertexBuffer] as VertexBuffer;
				if(_VertexBuffer==null)
				{
					_VertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedColoredTextured), 6, m_Device, Usage.WriteOnly | Usage.Dynamic, 0, Pool.SystemMemory);
					Cerebrum.Direct3D.Drawing.Graphics.DeviceObjects[m_Device, m__VertexBuffer] = _VertexBuffer;

					CustomVertex.TransformedColoredTextured[] fontVertices = new CustomVertex.TransformedColoredTextured[6];

					float xpos;
					float ypos;
					float w;
					float h;

					xpos = rectangle.X;
					ypos = rectangle.Y;
					w = rectangle.Width;
					h = rectangle.Height;

					float tx1 = 0;
					float ty1 = 0;
					float tx2 = 1.0f;
					float ty2 = 1.0f;
					float z = this.m_Z;

					int clr = System.Drawing.Color.Yellow.ToArgb();

					fontVertices[0] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+0-0.5f,ypos+h-0.5f,z,1.0f), clr, tx1, ty2);
					fontVertices[1] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+0-0.5f,ypos+0-0.5f,z,1.0f), clr, tx1, ty1);
					fontVertices[2] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+w-0.5f,ypos+h-0.5f,z,1.0f), clr, tx2, ty2);
					fontVertices[3] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+w-0.5f,ypos+0-0.5f,z,1.0f), clr, tx2, ty1);
					fontVertices[4] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+w-0.5f,ypos+h-0.5f,z,1.0f), clr, tx2, ty2);
					fontVertices[5] = new CustomVertex.TransformedColoredTextured(new Vector4(xpos+0-0.5f,ypos+0-0.5f,z,1.0f), clr, tx1, ty1);

					_VertexBuffer.SetData(fontVertices, 0, LockFlags.Discard);
				}


				RenderStateManager renderState = m_Device.RenderState;

				renderState.AlphaBlendEnable = true;
				renderState.SourceBlend = Blend.SourceAlpha;
				renderState.DestinationBlend = Blend.InvSourceAlpha;
				renderState.AlphaTestEnable = true;
				renderState.ReferenceAlpha = 0x08;
				renderState.AlphaFunction = Compare.GreaterEqual;

				TextureStateManager textureState0;

				textureState0 = m_Device.TextureState[0];

				textureState0.ColorOperation = TextureOperation.Modulate;
				textureState0.ColorArgument1 = TextureArgument.TextureColor;
				textureState0.ColorArgument2 = TextureArgument.Diffuse;
				textureState0.AlphaOperation = TextureOperation.Modulate;
				textureState0.AlphaArgument1 = TextureArgument.TextureColor;
				textureState0.AlphaArgument2 = TextureArgument.Diffuse;
				textureState0.TextureCoordinateIndex = 0;
				textureState0.TextureTransform = TextureTransform.Disable; // REVIEW

				m_Device.SetTexture(0, _ImageTexture);
				m_Device.VertexFormat = CustomVertex.TransformedColoredTextured.Format;
				m_Device.PixelShader = null;

				m_Device.SetStreamSource(0, _VertexBuffer, 0);
				m_Device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
				m_Device.SetTexture(0, null);
			}
			// End the scene
			m_Device.EndScene();
		}

		
		/// <summary>
		/// Setup the matrices
		/// </summary>
		private void SetupMatrices()
		{
			// move the object
			/*Matrix temp = Matrix.Translation(-(bufferSize*0.6f), 0, 0);//-(bufferSize*0.5f));

			// For our world matrix, we will just rotate the object about the indexY-axis.
			m_Device.Transform.World = Matrix.Multiply(temp, Matrix.RotationAxis(new Vector3(0,
				1.0f,
				0), 
				(Environment.TickCount % 7200) / 3600.0f * (float)Math.PI));*/
			/*temp;*/
			// Set up our view matrix. A view matrix can be defined given an eye point,
			// a point to lookat, and a direction for which way is up. Here, we set the
			// eye five units back along the z-axis and up three units, look at the
			// origin, and define "up" to be in the indexY-direction.
			/*m_Device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 25.0f,-30.0f),
				new Vector3(0.0f, 0.0f, 0.0f), 
				new Vector3(0.0f, 1.0f, 0.0f));*/

			/*m_Device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 0.0f, 10.0f),
				new Vector3(0.0f, 0.0f, 0.0f), 
				new Vector3(0.0f, 1.0f, 0.0f));*/
			// For the projection matrix, we set up a perspective transform (which
			// transforms geometry from 3D view space to 2D viewport space, with
			// a perspective divide making objects smaller in the distance). To build
			// a perpsective transform, we need the field of view (1/4 pi is common),
			// the aspect ratio, and the near and far clipping planes (which define at
			// what distances geometry should be no longer be rendered).
			//m_Device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, 1.0f, 0.0f, 100.0f);
			/*m_Device.Transform.Projection = Matrix.PerspectiveOffCenterLH(-10, 10, -10, 10, -10, 10);*/


		}

        
        
        
        
		/// <summary>
		/// Setup the lights
		/// </summary>
		private void SetupLights()
		{
			Color col = Color.White;
			//Set up a material. The material here just has the diffuse and ambient
			//colors set to yellow. Note that only one material can be used at a time.
			Material mtrl = new Material();
			mtrl.Diffuse = 	mtrl.Ambient = col;
			m_Device.Material = mtrl;
			
			//Set up a white, directional light, with an oscillating direction.
			//Note that many lights may be active at a time (but each one slows down
			//the rendering of our scene). However, here we are just using one. Also,
			//we need to set the D3DRS_LIGHTING renderstate to enable lighting
    
			System.DateTime time = new DateTime(this.m_DeviceTime.Year, this.m_DeviceTime.Month, this.m_DeviceTime.Day);
			System.TimeSpan span = this.m_DeviceTime - time;

			double angle = span.TotalSeconds;

			m_Device.Lights[0].Type = LightType.Directional;
			m_Device.Lights[0].Diffuse = Color.Purple;
			m_Device.Lights[0].Direction = new Vector3((float)Math.Sin(angle), (float)Math.Cos(angle),	0);

#warning "porting"
			//m_Device.Lights[0].Commit();
			m_Device.Lights[0].Enabled = true;

			//Finally, turn on some ambient light.
			//Ambient light is light that scatters and lights all objects evenly
			m_Device.RenderState.Ambient = Color.Gray;
		}

		private void ControlRepeater_CreateRepeatedControl(object sender, Cerebrum.Direct3D.Forms.ControlRepeaterEventArgs re)
		{
			ObjectiveDraw.Platform.Controls.RepeatedLabel repeatedLabel;

			repeatedLabel = new ObjectiveDraw.Platform.Controls.RepeatedLabel();
			repeatedLabel.Label.Font = this.m_Direct3DFont;
			repeatedLabel.Label.ForeColor = System.Drawing.Color.Yellow;
			repeatedLabel.Size = new System.Drawing.SizeF(this.Size.Width, 16);
			repeatedLabel.TextLines = this.m_TextLines;
			re.RepeatedControl = repeatedLabel;
		}
	}
}
